package com.kbbywyclient.util;

import android.content.Context;
import android.util.Base64;


import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;

/**
 * RAS加密解密工具类
 * Created by zad
 * 2017/2/15 10:52
 */

public class RSAUtil {
    /**
     * RSA最大加密明文大小
     */
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * RSA最大解密密文大小
     */
    private static final int MAX_DECRYPT_BLOCK = 128;

    public static final String KEY_ALGORITHM = "RSA";

    private static String PUBLIC_KEY = null;

    private static String PRIVATE_KEY = null;

    /**
     * TODO 私钥解密
     *
     * @param intputStr 要解密的base64字符串
     * @param keyBase64 私钥base64
     * @return
     */
    public static String decryptByPrivateKey(String intputStr, String keyBase64) {
        ByteArrayOutputStream out = null;
        try {
            //获取私钥
            Key privateKey = getPrivateKey(keyBase64);
            // 对数据分段解密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] intputBytes = Base64.decode(intputStr, Base64.DEFAULT);
            int inputLen = intputBytes.length;
            out = new ByteArrayOutputStream();
            int offSet = 0;
            byte[] cache;
            int i = 0;
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
                    cache = cipher.doFinal(intputBytes, offSet, MAX_DECRYPT_BLOCK);
                } else {
                    cache = cipher.doFinal(intputBytes, offSet, inputLen - offSet);
                }
                out.write(cache, 0, cache.length);
                i++;
                offSet = i * MAX_DECRYPT_BLOCK;
            }
            byte[] decryptedData = out.toByteArray();
            return new String(decryptedData);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException
                | BadPaddingException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * TODO RSA 公钥加密
     *
     * @param inputStr  需要加密字符串
     * @param keyBase64 公钥base64
     * @return
     * @throws Exception
     */
    public static String encryptByPublicKey(String inputStr, String keyBase64) {
        ByteArrayOutputStream bos = null;
        try {
            Key publicKey = getPublicKey(keyBase64);
            // 对数据加密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] inputData = inputStr.getBytes();
            int inputLen = inputData.length;
            bos = new ByteArrayOutputStream();
            int offSet = 0;
            int i = 0;
            byte[] buffer;
            // 对数据分段加密
            while (inputLen - offSet > 0) {
                if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                    buffer = cipher.doFinal(inputData, offSet, MAX_ENCRYPT_BLOCK);
                } else {
                    buffer = cipher.doFinal(inputData, offSet, inputLen - offSet);
                }
                bos.write(buffer, 0, buffer.length);
                i++;
                offSet = i * MAX_ENCRYPT_BLOCK;
            }
            return Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException | InvalidKeyException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 获取公钥
     *
     * @param keyBase64
     * @return
     */
    public static Key getPublicKey(String keyBase64) {
        try {
            // 对公钥解密
            byte[] publicKeyBytes = Base64.decode(keyBase64.getBytes(), Base64.DEFAULT);
            // 取得公钥
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            Key publicKey = keyFactory.generatePublic(x509KeySpec);
            return publicKey;
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取私钥
     *
     * @param keyBase64
     * @return
     */
    public static Key getPrivateKey(String keyBase64) {
        // 对密钥解密
        byte[] privateKeyBytes = Base64.decode(keyBase64.getBytes(), Base64.DEFAULT);
        // 取得私钥
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
        try {
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
            return keyFactory.generatePrivate(pkcs8KeySpec);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return null;
    }

//    public static String getPublicKey(Context context) {
//        if (PUBLIC_KEY == null) {
//            try {
//                //jni代码有点兼容性问题未解决
//                PUBLIC_KEY = /*JNIKey.getPublicKey(context) + */context.getResources().getString(R.string.key_1) + BuildConfig.key_1;
//            } catch (Throwable e) {
//                e.printStackTrace();
//            }
//        }
//        return PUBLIC_KEY;
//    }
//
//    public static String getPrivateKey(Context context) {
//        if (PRIVATE_KEY == null) {
//            try {
//                //jni代码有点兼容性问题未解决
//                PRIVATE_KEY = /*JNIKey.getPrivateKey(context) + */context.getResources().getString(R.string.key_2) + BuildConfig.key_2;
//            } catch (Throwable e) {
//                e.printStackTrace();
//            }
//        }
//        return PRIVATE_KEY;
//    }
}